package com.tencent.sr.iris.activity.service.activity.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.tencent.sr.iris.activity.common.enums.IrisErrorCode;
import com.tencent.sr.iris.activity.common.util.AssertUtils;
import com.tencent.sr.iris.activity.dependency.basic.BasicDependency;
import com.tencent.sr.iris.activity.dependency.user.UserCoreDependency;
import com.tencent.sr.iris.activity.interfaces.dto.AwardInfoDTO;
import com.tencent.sr.iris.activity.interfaces.request.IrisPaginationRequest;
import com.tencent.sr.iris.activity.interfaces.request.acticity.*;
import com.tencent.sr.iris.activity.interfaces.response.activity.ActivityAwardInfoResponse;
import com.tencent.sr.iris.activity.interfaces.response.activity.ActivityMonthLimitResponse;
import com.tencent.sr.iris.activity.interfaces.response.activity.ActivityUidLimitResponse;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisActivityTaskService;
import com.tencent.sr.iris.activity.service.activity.IrisUserTaskRecordService;
import com.tencent.sr.iris.activity.service.config.ActivityConfig;
import com.tencent.sr.iris.activity.service.constant.ActivityConfigConstants;
import com.tencent.sr.iris.activity.service.constant.ActivityRedisKey;
import com.tencent.sr.iris.basic.service.interfaces.dto.TCommonKvConfigDTO;
import com.tencent.sr.iris.basic.service.interfaces.request.TCommonKvConfigAddRequest;
import com.tencent.sr.iris.basic.service.interfaces.request.TCommonKvConfigBatchQueryRequest;
import com.tencent.sr.iris.basic.service.interfaces.request.TCommonKvConfigQueryPageRequest;
import com.tencent.sr.iris.basic.service.interfaces.request.TCommonKvConfigUpdateRequest;
import com.tencent.sr.iris.basic.service.interfaces.response.CommonConfigCountResponse;
import com.tencent.sr.iris.user.core.service.interfaces.dto.user.UserWideDTO;
import com.tencent.sr.iris.user.core.service.interfaces.request.user.IrisUserWideListQueryRequest;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserInfoQueryResponse;
import com.tencent.sr.rmall.common.exception.retail.TRetailBizException;
import com.tencent.sr.rmall.common.primitive.HttpResult;
import com.tencent.sr.rmall.common.request.PaginationRequest;
import com.tencent.sr.rmall.common.response.PaginationResponse;
import com.tencent.sr.rmall.springbootstarter.redis.RedisClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class IrisActivityConfigService {

    @Resource
    private BasicDependency basicDependency;

    @Resource
    private UserCoreDependency userCoreDependency;

    @Resource
    private IrisUserTaskRecordService userTaskRecordService;

    @Resource
    private ActivityCommonService activityCommonService;
    
    @Resource
    private IrisUserTaskRecordService irisUserTaskRecordService;
    
    @Resource
    private RedisClient redisClient;
    @Resource
    private IrisActivityTaskService irisActivityTaskService;
    @Resource
    private ActivityConfig activityConfig;


    public PaginationResponse<ActivityMonthLimitResponse> monthLimitConfigPage(PaginationRequest request) {
        Integer pageSize = request.getPageSize();
        Integer pageNum = request.getPageNum();

        TCommonKvConfigQueryPageRequest queryPageRequest = new TCommonKvConfigQueryPageRequest();
        PaginationRequest<TCommonKvConfigQueryPageRequest> basicReq = new IrisPaginationRequest<>();
        basicReq.setPageSize(pageSize);
        basicReq.setPageNum(pageNum);
        basicReq.setQueryCriteria(queryPageRequest);
        queryPageRequest.setParentKey(ActivityConfigConstants.MONTH_LIMIT_PARENT_CONFIG_KEY);

        PaginationResponse<ActivityMonthLimitResponse> res = new PaginationResponse<>();
        res.setPageSize(pageSize);
        res.setPageNum(pageNum);

        PaginationResponse<TCommonKvConfigDTO> response = basicDependency.queryCommonKVPage(basicReq);
        if (response == null || CollectionUtil.isEmpty(response.getDataList())) {
            res.setTotalCount(0);
            res.setDataList(Collections.emptyList());
            return res;
        }

        //查询下级配置数据
        List<String> configKeys = response.getDataList().stream()
                .map(TCommonKvConfigDTO::getConfigKey).collect(Collectors.toList());
        List<CommonConfigCountResponse> countResponses = basicDependency.countConfigUnderParentConfig(configKeys);
        Map<String, Long> countMap = countResponses.stream().collect(Collectors.toMap(
                CommonConfigCountResponse::getConfigKey, CommonConfigCountResponse::getCount, (i1, i2) -> i1));

        List<ActivityMonthLimitResponse> limitResponses = response.getDataList().stream().map(i -> {
            String configKey = i.getConfigKey();
            ActivityMonthLimitResponse monthLimitResponse = new ActivityMonthLimitResponse()
                    .setConfigId(i.getId())
                    .setSubConfigCount(countMap.getOrDefault(configKey, 0l))
                    .setConfigKey(configKey);
            try {
                Date dateTime = DateUtil.parseDateTime(i.getConfigValue());
                return monthLimitResponse.setConfigDate(
                        Optional.ofNullable(dateTime).map(Date::getTime).orElse(null));
            } catch (Exception e) {
                log.error("获取限额配置错误：", e);
            }
            return monthLimitResponse;
        }).collect(Collectors.toList());
        res.setTotalCount(response.getTotalCount());
        res.setDataList(limitResponses);
        return res;
    }

    public PaginationResponse<ActivityUidLimitResponse> uidLimitConfigPage(
            IrisPaginationRequest<ActivityUidLimitPageRequest> request) {
        Integer pageSize = request.getPageSize();
        Integer pageNum = request.getPageNum();
        ActivityUidLimitPageRequest queryCriteria = request.getQueryCriteria();

        TCommonKvConfigQueryPageRequest queryPageRequest = new TCommonKvConfigQueryPageRequest();
        PaginationRequest<TCommonKvConfigQueryPageRequest> basicReq = new IrisPaginationRequest<>();
        basicReq.setPageSize(pageSize);
        basicReq.setPageNum(pageNum);
        queryPageRequest.setParentKey(queryCriteria.getParentKey());

        String uidParam = queryCriteria.getUid();
        if (StringUtils.isNotBlank(uidParam)) {
            String key = String.format(ActivityConfigConstants.MONTH_LIMIT_CONFIG_UID_KEY, uidParam);
            queryPageRequest.setConfigKeyList(Arrays.asList(key));
        }

        basicReq.setQueryCriteria(queryPageRequest);
        PaginationResponse<ActivityUidLimitResponse> res = new PaginationResponse<>();
        res.setPageSize(pageSize);
        res.setPageNum(pageNum);

        PaginationResponse<TCommonKvConfigDTO> response = basicDependency.queryCommonKVPage(basicReq);
        if (response == null || CollectionUtil.isEmpty(response.getDataList())) {
            res.setTotalCount(0);
            res.setDataList(Collections.emptyList());
            return res;
        }

        List<TCommonKvConfigDTO> dataList = response.getDataList();
        List<String> uidList = dataList.stream()
                .map(i -> i.getConfigKey().replace(ActivityConfigConstants.MONTH_LIMIT_CONFIG_UID_BASE_KEY, ""))
                .collect(Collectors.toList());
        IrisUserWideListQueryRequest userReq = new IrisUserWideListQueryRequest();
        userReq.setUidList(uidList);
        List<UserWideDTO> userList = userCoreDependency.batchQueryUserList(userReq);
        Map<String, UserWideDTO> wideDTOMap = userList.stream()
                .collect(Collectors.toMap(UserWideDTO::getUid, i -> i, (i1, i2) -> i1));

        List<ActivityUidLimitResponse> limitResponses = dataList.stream()
                .map(i -> getActivityUidLimitResponse(i, wideDTOMap)).collect(Collectors.toList());
        res.setTotalCount(response.getTotalCount());
        res.setDataList(limitResponses);
        return res;
    }

    /**
     * 转换响应结果
     *
     * @param i
     * @param wideDTOMap
     * @return
     */
    private ActivityUidLimitResponse getActivityUidLimitResponse(TCommonKvConfigDTO i,
            Map<String, UserWideDTO> wideDTOMap) {
        ActivityUidLimitResponse uidLimitResponse = new ActivityUidLimitResponse();
        try {
            String configKey = i.getConfigKey();
            String parentKey = i.getParentKey();
            String uid = configKey.replace(ActivityConfigConstants.MONTH_LIMIT_CONFIG_UID_BASE_KEY, "");
            String monthStr = parentKey.replace(ActivityConfigConstants.MONTH_LIMIT_CONFIG_MONTH_BASE_KEY, "");

            long count = userTaskRecordService.queryContributedUserCount(uid, monthStr);

            //用户信息
            Integer levelInviteLimit = null;
            UserWideDTO userWideDTO = wideDTOMap.get(uid);
            if (userWideDTO != null) {
                uidLimitResponse.setNickName(userWideDTO.getNickName())
                        .setUid(uid).setLevel(userWideDTO.getLevelId());
                levelInviteLimit = activityCommonService.getLevelInviteLimit(userWideDTO.getLevelId(), uid);
            }
            //设置等级限制
            Integer limit = NumberUtil.isNumber(i.getConfigValue())
                    ? Integer.valueOf(i.getConfigValue()) : null;
            return uidLimitResponse.setConfigId(i.getId())
                    .setUid(uid).setLimit(limit).setLevelLimit(levelInviteLimit)
                    .setLimitUsed(Math.toIntExact(count)).setConfigKey(configKey);
        } catch (Exception e) {
            log.error("获取uid邀请限额错误：", e);
        }
        return uidLimitResponse;
    }

    public Boolean addCurrentMonthLimit(ActivityMonthLimitAddRequest request) {
        Date configDate = DateUtil.date(request.getConfigDate());
        boolean canConfig = YearMonth.from(configDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
                .compareTo(YearMonth.now()) >= 0;
        AssertUtils.isTrue(canConfig, IrisErrorCode.ACTIVITY_LIMIT_CONFIG_DATE_ERROR);

        String monthStr = DateUtil.format(configDate, "yyyyMM");
        String key = String.format(ActivityConfigConstants.MONTH_LIMIT_CONFIG_MONTH_KEY, monthStr);
        TCommonKvConfigAddRequest addRequest = new TCommonKvConfigAddRequest();
        addRequest.setParentKey(ActivityConfigConstants.MONTH_LIMIT_PARENT_CONFIG_KEY);
        addRequest.setConfigKey(key);
        addRequest.setConfigValue(DateUtil.formatDateTime(configDate));
        addRequest.setName(monthStr + "邀请限额配置");
        addRequest.setOperateId(request.getOperatorUid());
        return basicDependency.add(addRequest);
    }

    public Boolean addUidLimit(ActivityUidLimitAddRequest request) {
        String uid = request.getUid();
        UserInfoQueryResponse userInfo = userCoreDependency.queryUserInfo(uid, false);

        boolean valid = userInfo != null && userInfo.getUserInfoDTO() != null;
        AssertUtils.isTrue(valid, IrisErrorCode.USER_NOT_EXIST);

        String key = String.format(ActivityConfigConstants.MONTH_LIMIT_CONFIG_UID_KEY, uid);
        TCommonKvConfigAddRequest addRequest = new TCommonKvConfigAddRequest();
        addRequest.setParentKey(request.getParentKey());
        addRequest.setConfigKey(key);
        addRequest.setConfigValue(Optional.ofNullable(request.getLimit()).map(String::valueOf).orElse(StrUtil.EMPTY));
        addRequest.setName(uid + "邀请限额配置");
        addRequest.setOperateId(request.getOperatorUid());
        return basicDependency.add(addRequest);
    }

    public Boolean updateUidLimit(ActivityUidLimitUpdateRequest request) {
        TCommonKvConfigBatchQueryRequest queryRequest = new TCommonKvConfigBatchQueryRequest();
        queryRequest.setId(request.getId());
        queryRequest.setParentKey(null);
        List<TCommonKvConfigDTO> configs = basicDependency.batchQueryCommonKVNoCache(queryRequest);
        AssertUtils.isNotEmpty(configs, IrisErrorCode.DATA_NOT_EXIST);
        TCommonKvConfigDTO uidConfig = configs.get(0);
        String uid = uidConfig.getConfigKey().replace(ActivityConfigConstants.MONTH_LIMIT_CONFIG_UID_BASE_KEY, "");

        //查询父级配置
        String parentKey = uidConfig.getParentKey();
        queryRequest = new TCommonKvConfigBatchQueryRequest();
        queryRequest.setConfigKeyList(Arrays.asList(parentKey));
        queryRequest.setParentKey(ActivityConfigConstants.MONTH_LIMIT_PARENT_CONFIG_KEY);
        configs = basicDependency.batchQueryCommonKVNoCache(queryRequest);
        AssertUtils.isNotEmpty(configs, IrisErrorCode.DATA_NOT_EXIST);
        TCommonKvConfigDTO monthConfig = configs.get(0);
        String configValue = monthConfig.getConfigValue();
        String monthStr = null;
        // 仅当月或未来月份可修改
        boolean canConfig = false;
        long userCount = 0;
        try {
            Date configDate = DateUtil.parse(configValue);
            canConfig = YearMonth.from(configDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
                    .compareTo(YearMonth.now()) >= 0;
            monthStr = DateUtil.format(configDate, "yyyyMM");
            userCount = userTaskRecordService.queryContributedUserCount(uid, monthStr);

            String cacheKey = String.format(ActivityRedisKey.ACTIVITY_INVITE_LIMIT_KEY, monthStr, uid);
            redisClient.del(cacheKey);
        } catch (Exception e) {
            log.error("解析月份配置日期失败：", e);
        }
        AssertUtils.isTrue(canConfig, IrisErrorCode.ACTIVITY_LIMIT_CONFIG_DATE_ERROR);
        AssertUtils.isGreaterEquals((long) request.getLimit(), userCount, IrisErrorCode.LIMIT_LESS_THAN_CONTRIBUTED);

        TCommonKvConfigUpdateRequest updateRequest = new TCommonKvConfigUpdateRequest();
        updateRequest.setId(String.valueOf(request.getId()));
        updateRequest.setConfigValue(String.valueOf(request.getLimit()));
        updateRequest.setOperateId(request.getOperatorUid());
        Boolean result = basicDependency.update(updateRequest);
        if(BooleanUtil.isTrue(result)){
            log.info("updateUidLimit success request:{},result:{}", JSON.toJSONString(request), result);
        } else {
            log.error("updateUidLimit error request:{},result:{}", JSON.toJSONString(request), result);
            return result;
        }
        ProcessUpdateLimitRequest req = ProcessUpdateLimitRequest
                .builder()
                .uid(uid)
                .limit(request.getLimit())
                .month(monthStr)
                .build();
        HttpResult<String> result1 = irisUserTaskRecordService.processUpdateLimit(req);
        if(!result1.isSuccess()){
            log.error("修改uid发奖限额，处理下级发奖失败uid:" + uid);
            throw new TRetailBizException("修改uid发奖限额，处理下级发奖失败,uid:" + uid);
        }
        return result;
    }

    /**
     * 查询活动奖励配置金额
     * @param request
     * @return
     */
    public ActivityAwardInfoResponse getConfigAwardInfo(GetActivityConfigAwardRequest request) {
        //获取最新的一条有效配置
        AwardInfoDTO info = irisActivityTaskService.getValidAwardInfoLastOne(request.getBizId());
        if(info == null){
            return null;
        }
        ActivityAwardInfoResponse response = new ActivityAwardInfoResponse();
        BeanUtils.copyProperties(info, response);
        // 活动对应的文案配置
        String desc = activityConfig.getBizIdDescMap().get(request.getBizId());
        response.setDesc(desc);
        return response;
    }
}
